using System;
using System.Collections;

using LocalBoard.Domain;
using LocalBoard.Persistence;

namespace LocalBoard.Controller
{
	/// <summary>
	/// Summary description for BoardController.
	/// </summary>
	public class BoardController
	{
		private int _boardId = 0;
		public int BoardId
		{
			get {return _boardId;}
		}
		private ClubController _clubController = null;
		protected ClubController ClubController
		{
			get {return _clubController;}
		}
		private int _currentPageNo = 0;
		public int CurrentPageNo
		{
			get{return _currentPageNo;}
		}
		private IAccessorFactory _accessorFactory;
		protected IAccessorFactory AccessorFactory
		{
			get {return _accessorFactory;}
		}
		public const int MessageNumberPerPage = 20;

		public BoardController(int boardId, ClubController clubController, int currentPageNo, IAccessorFactory accessorFactory)
		{
			if(clubController == null)
				throw new ArgumentNullException("clubController");
			if(accessorFactory == null)
				throw new ArgumentNullException("accessorFactory");
			_boardId = boardId;
			_clubController = clubController;
			_currentPageNo = currentPageNo > 0 ? currentPageNo : 1;
			_accessorFactory = accessorFactory;
		}

		public virtual int TotalRootMessageCount
		{
			get{return _accessorFactory.GetMessageAccessor().GetTotalRootMessageCountByBoardId(_boardId);}
		}

		public virtual int TotalPageNumber
		{
			get
			{
				int totalPageNumber = TotalRootMessageCount / MessageNumberPerPage;
				return (TotalRootMessageCount % MessageNumberPerPage > 0) ? totalPageNumber + 1 : totalPageNumber;
			}
		}
		public bool HasPreviousPage
		{
			get
			{
				if(_currentPageNo > 1) return true;
				return false;
			}
		}
		public bool HasNextPage
		{
			get
			{
				if(_currentPageNo < TotalPageNumber) return true;
				return false;
			}
		}

		public virtual ArrayList GetMessageListForCurrentPage()
		{
			return _accessorFactory.GetMessageAccessor().GetMessageListByBoardId(_boardId, MessageNumberPerPage, _currentPageNo);
		}

		public Message GetMessage(int messageId)
		{
			return _accessorFactory.GetMessageAccessor().Get(messageId);
		}

		public void UpdateMessageOld(Message message)
		{
			_accessorFactory.GetMessageAccessor().Update(message);
		}
		public void EditMessage(Message orgMessage, string subject, string body)
		{
			orgMessage.Subject = subject;
			orgMessage.Body = body;
			_accessorFactory.GetMessageAccessor().Update(orgMessage);
		}

		public void DeleteMessage(int messageId)
		{
			_accessorFactory.GetMessageAccessor().Delete(messageId);
		}

		/// <summary>
		/// Post the passed message object to the board linked to the club control
		/// </summary>
		/// <param name="message">Message object to post</param>
		/// <returns>Id created in the db for new message</returns>
		public virtual int PostMessage(Message message)
		{
			if(message == null)
				throw new ArgumentNullException("message");
			Message copiedMessage = message;
			copiedMessage.BoardId = _boardId;
			return _accessorFactory.GetMessageAccessor().Insert(copiedMessage);
		}
		/// <summary>
		/// Post a new message to the board linked to the club control
		/// </summary>
		/// <param name="subject">Subject of new message</param>
		/// <param name="body">Body of new message</param>
		/// <param name="user">User object who is posting new message</param>
		/// <param name="replyToMessageId">Id of a message which new message is replying to</param>
		/// <returns>Id created in the db for new message</returns>
		public virtual int PostMessage(string subject, string body, Profile user, int replyToMessageId)
		{
			return PostMessage(new Message(subject,body,user.UserName,user.UserId,user,_boardId,_clubController.ClubId, replyToMessageId));
		}

		public virtual int PostPollMessage(string subject, string body, Profile user, int replyToMessageId)
		{
			return _accessorFactory.GetMessageAccessor().Insert(new PollMessage(subject,body,user.UserName,user.UserId,user,_boardId,_clubController.ClubId, replyToMessageId));
		}

		public void IncreaseHits(Profile user, ref Message message)
		{
			if(ShouldIncreaseHits(user, message))
			{
				message.Hits++; //increase in-memory object first
				_accessorFactory.GetMessageAccessor().IncreaseHit(message);
			}
		}

		/// <summary>
		/// Get board security object for the user and board linked to the club control
		/// </summary>
		/// <param name="user">User context</param>
		/// <returns>Board security object</returns>
		public virtual BoardSecurity GetBoardSecurity(Profile user)
		{
			BoardSecurity security = GetBoardSecurity();
			security.SetTargetUser(user);
			return security;
		}
		/// <summary>
		/// Get board security object for the board linked to the club control
		/// </summary>
		/// <returns>Board security object</returns>
		public virtual BoardSecurity GetBoardSecurity()
		{
			return new BoardSecurity(_accessorFactory.GetBoardAccessor().Get(_boardId), _clubController);
		}
//		/// <summary>
//		/// Get board security object for the user and board
//		/// </summary>
//		/// <param name="user">User context</param>
//		/// <param name="boardId">Board id that security is bound to</param>
//		/// <returns>Board security object</returns>
//		public BoardSecurity GetBoardSecurity(Profile user, int boardId)
//		{
//			BoardSecurity security = GetBoardSecurity(boardId);
//			security.SetTargetUser(user);
//			return security;
//		}
//		/// <summary>
//		/// Get board security object for the board
//		/// </summary>
//		/// <param name="boardId">Board id that security is bound to</param>
//		/// <returns>Board security object</returns>
//		public BoardSecurity GetBoardSecurity(int boardId)
//		{
//			return new BoardSecurity(_accessorFactory.GetBoardAccessor().Get(boardId), _clubController);
//		}

		private bool ShouldIncreaseHits(Profile user, Message message)
		{
			return (user == null || user.Id == 0 || user.Equals(new AdminController(_accessorFactory).GetAnonymousUser())
				|| (message != null && (message.Author == null || user.Id != message.Author.Id)));
		}

		public void RateMessage(int messageId, int profileId, int rate)
		{
			_accessorFactory.GetMessageAccessor().InsertVote(messageId, profileId, rate);
		}

		/// <summary>
		/// Get list of votes that users rated for a message
		/// </summary>
		/// <param name="messageId">Message id</param>
		/// <returns>List of <see cref="Vote">Vote</see>s</returns>
		public ArrayList GetRateListByMessageId(int messageId)
		{
			return _accessorFactory.GetMessageAccessor().GetVoteList(messageId);
		}
	}
}
